Розкрийте потенціал Федерації GraphQL за допомогою зшивання схем. Дізнайтеся, як створити єдиний GraphQL API з кількох сервісів, покращуючи масштабованість та підтримку.
Федерація GraphQL: Зшивання схем - вичерпний посібник
У світі розробки сучасних додатків, що постійно розвивається, потреба в масштабованих архітектурах, які легко підтримувати, стала першочерговою. Мікросервіси, з їхньою притаманною модульністю та незалежним розгортанням, стали популярним рішенням. Однак управління численними мікросервісами може створювати складнощі, особливо коли йдеться про надання єдиного API для клієнтських додатків. Саме тут на допомогу приходить Федерація GraphQL, а зокрема — зшивання схем (Schema Stitching).
Що таке Федерація GraphQL?
Федерація GraphQL — це потужна архітектура, яка дозволяє створювати єдиний, уніфікований GraphQL API з кількох базових сервісів GraphQL (які часто представляють мікросервіси). Вона дає змогу розробникам запитувати дані з різних сервісів так, ніби це єдиний граф, що спрощує роботу клієнта та зменшує потребу в складній логіці оркестрації на стороні клієнта.
Існує два основних підходи до Федерації GraphQL:
- Зшивання схем (Schema Stitching): Цей підхід передбачає об'єднання кількох схем GraphQL в одну, уніфіковану схему на рівні шлюзу. Це більш ранній підхід, який покладається на бібліотеки для управління комбінуванням схем та делегуванням запитів.
- Apollo Federation: Це новіший і надійніший підхід, який використовує декларативну мову схем і спеціалізований планувальник запитів для управління процесом федерації. Він пропонує розширені функції, такі як розширення типів, ключові директиви та розподілене трасування.
Ця стаття зосереджена на зшиванні схем, досліджуючи його концепції, переваги, обмеження та практичну реалізацію.
Розуміння зшивання схем
Зшивання схем — це процес об'єднання кількох схем GraphQL в одну, цілісну схему. Ця уніфікована схема діє як фасад, приховуючи складність базових сервісів від клієнта. Коли клієнт робить запит до зшитої схеми, шлюз розумно маршрутизує запит до відповідного сервісу(-ів), отримує дані та поєднує результати перед тим, як повернути їх клієнту.
Уявіть собі це так: у вас є кілька ресторанів (сервісів), кожен з яких спеціалізується на різних кухнях. Зшивання схем — це як універсальне меню, що поєднує всі страви з кожного ресторану. Коли клієнт (замовник) робить замовлення з універсального меню, замовлення розумно направляється на кухні відповідних ресторанів, їжа готується, а потім об'єднується в одну доставку для клієнта.
Ключові концепції зшивання схем
- Віддалені схеми: Це індивідуальні схеми GraphQL кожного базового сервісу. Кожен сервіс надає власну схему, яка визначає дані та операції, що він пропонує.
- Шлюз: Шлюз — це центральний компонент, відповідальний за зшивання віддалених схем та надання уніфікованої схеми клієнту. Він отримує клієнтські запити, маршрутизує їх до відповідних сервісів та поєднує результати.
- Об'єднання схем: Це процес комбінування віддалених схем в єдину схему. Це часто включає перейменування типів і полів для уникнення конфліктів та визначення зв'язків між типами з різних схем.
- Делегування запитів: Коли клієнт робить запит до зшитої схеми, шлюз повинен делегувати запит відповідному сервісу(-ам) для отримання даних. Це включає перетворення запиту клієнта на запит, який може зрозуміти віддалений сервіс.
- Агрегація результатів: Після того, як шлюз отримав дані з базових сервісів, він повинен об'єднати результати в єдину відповідь, яку можна повернути клієнту. Це часто включає перетворення даних для відповідності структурі зшитої схеми.
Переваги зшивання схем
Зшивання схем пропонує кілька значних переваг для організацій, що використовують мікросервісну архітектуру:
- Єдиний API: Надає єдиний, послідовний API для клієнтів, спрощуючи доступ до даних і зменшуючи потребу клієнтів взаємодіяти з кількома сервісами напряму. Це призводить до чистішого та інтуїтивно зрозумілішого досвіду для розробників.
- Зменшення складності на стороні клієнта: Клієнтам потрібно взаємодіяти лише з уніфікованою схемою, що захищає їх від складнощів базової мікросервісної архітектури. Це спрощує розробку на стороні клієнта та зменшує кількість коду, необхідного для клієнта.
- Підвищена масштабованість: Дозволяє масштабувати окремі сервіси незалежно, виходячи з їхніх конкретних потреб. Це покращує загальну масштабованість та стійкість системи. Наприклад, сервіс користувачів, що зазнає високого навантаження, може бути масштабований без впливу на інші сервіси, такі як каталог продуктів.
- Покращена підтримка: Сприяє модульності та розділенню відповідальності, що полегшує підтримку та розвиток окремих сервісів. Зміни в одному сервісі менш імовірно вплинуть на інші сервіси.
- Поступове впровадження: Може бути реалізовано інкрементально, дозволяючи поступово переходити від монолітної архітектури до мікросервісної. Ви можете почати зі зшивання існуючих API, а потім поступово розкладати моноліт на менші сервіси.
Обмеження зшивання схем
Хоча зшивання схем пропонує численні переваги, важливо знати про його обмеження:
- Складність: Впровадження та управління зшиванням схем може бути складним, особливо у великих і комплексних системах. Необхідне ретельне планування та проєктування.
- Накладні витрати на продуктивність: Шлюз створює певні накладні витрати на продуктивність через додатковий рівень абстракції та потребу делегувати запити й агрегувати результати. Ретельна оптимізація є вкрай важливою для мінімізації цих витрат.
- Конфлікти схем: Конфлікти можуть виникати при об'єднанні схем з різних сервісів, особливо якщо вони використовують однакові назви типів або полів. Це вимагає ретельного проєктування схем та потенційного перейменування типів і полів.
- Обмежені розширені функції: Порівняно з Apollo Federation, зшиванню схем бракує деяких розширених функцій, таких як розширення типів та ключові директиви, що може ускладнити управління зв'язками між типами з різних схем.
- Зрілість інструментів: Інструменти та екосистема навколо зшивання схем не настільки зрілі, як навколо Apollo Federation. Це може ускладнити налагодження та усунення несправностей.
Практична реалізація зшивання схем
Розгляньмо спрощений приклад того, як реалізувати зшивання схем за допомогою Node.js та бібліотеки graphql-tools
(популярний вибір для зшивання схем). Цей приклад включає два мікросервіси: сервіс користувачів та сервіс продуктів.
1. Визначте віддалені схеми
Спочатку визначте схеми GraphQL для кожного з віддалених сервісів.
Сервіс користувачів (user-service.js
):
const { buildSchema } = require('graphql');
const userSchema = buildSchema(`
type User {
id: ID!
name: String
email: String
}
type Query {
user(id: ID!): User
}
`);
const users = [
{ id: '1', name: 'Alice Smith', email: 'alice@example.com' },
{ id: '2', name: 'Bob Johnson', email: 'bob@example.com' },
];
const userRoot = {
user: (args) => users.find(user => user.id === args.id),
};
module.exports = {
schema: userSchema,
rootValue: userRoot,
};
Сервіс продуктів (product-service.js
):
const { buildSchema } = require('graphql');
const productSchema = buildSchema(`
type Product {
id: ID!
name: String
price: Float
userId: ID! # Зовнішній ключ до сервісу користувачів
}
type Query {
product(id: ID!): Product
}
`);
const products = [
{ id: '101', name: 'Laptop', price: 1200, userId: '1' },
{ id: '102', name: 'Smartphone', price: 800, userId: '2' },
];
const productRoot = {
product: (args) => products.find(product => product.id === args.id),
};
module.exports = {
schema: productSchema,
rootValue: productRoot,
};
2. Створіть сервіс шлюзу
Тепер створіть сервіс шлюзу, який зшиє дві схеми разом.
Сервіс шлюзу (gateway.js
):
const { stitchSchemas } = require('@graphql-tools/stitch');
const { makeRemoteExecutableSchema } = require('@graphql-tools/wrap');
const { graphqlHTTP } = require('express-graphql');
const express = require('express');
const { introspectSchema } = require('@graphql-tools/wrap');
const { printSchema } = require('graphql');
const fetch = require('node-fetch');
async function createRemoteSchema(uri) {
const fetcher = async (params) => {
const response = await fetch(uri, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(params),
});
return response.json();
};
const schema = await introspectSchema(fetcher);
return makeRemoteExecutableSchema({
schema,
fetcher,
});
}
async function main() {
const userSchema = await createRemoteSchema('http://localhost:4001/graphql');
const productSchema = await createRemoteSchema('http://localhost:4002/graphql');
const stitchedSchema = stitchSchemas({
subschemas: [
{ schema: userSchema },
{ schema: productSchema },
],
typeDefs: `
extend type Product {
user: User
}
`,
resolvers: {
Product: {
user: {
selectionSet: `{ userId }`,
resolve(product, args, context, info) {
return info.mergeInfo.delegateToSchema({
schema: userSchema,
operation: 'query',
fieldName: 'user',
args: {
id: product.userId,
},
context,
info,
});
},
},
},
},
});
const app = express();
app.use('/graphql', graphqlHTTP({
schema: stitchedSchema,
graphiql: true,
}));
app.listen(4000, () => console.log('Сервер шлюзу запущено на http://localhost:4000/graphql'));
}
main().catch(console.error);
3. Запустіть сервіси
Вам потрібно буде запустити сервіс користувачів та сервіс продуктів на різних портах. Наприклад:
Сервіс користувачів (порт 4001):
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { schema, rootValue } = require('./user-service');
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: rootValue,
graphiql: true,
}));
app.listen(4001, () => console.log('Сервіс користувачів запущено на http://localhost:4001/graphql'));
Сервіс продуктів (порт 4002):
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { schema, rootValue } = require('./product-service');
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: rootValue,
graphiql: true,
}));
app.listen(4002, () => console.log('Сервіс продуктів запущено на http://localhost:4002/graphql'));
4. Запитайте зшиту схему
Тепер ви можете надсилати запити до зшитої схеми через шлюз (який працює на порту 4000). Ви можете виконати такий запит:
query {
product(id: "101") {
id
name
price
user {
id
name
email
}
}
}
Цей запит отримує продукт з ID "101", а також отримує пов'язаного з ним користувача з сервісу користувачів, демонструючи, як зшивання схем дозволяє запитувати дані з кількох сервісів в одному запиті.
Просунуті техніки зшивання схем
Окрім базового прикладу, ось деякі просунуті техніки, які можна використовувати для покращення вашої реалізації зшивання схем:
- Делегування схеми: Це дозволяє делегувати частини запиту різним сервісам на основі даних, що запитуються. Наприклад, ви можете делегувати розв'язання типу `User` сервісу користувачів, а розв'язання типу `Product` — сервісу продуктів.
- Трансформація схеми: Це передбачає зміну схеми віддаленого сервісу перед тим, як її зшити в уніфіковану схему. Це може бути корисно для перейменування типів та полів, додавання нових полів або видалення існуючих.
- Кастомні резолвери: Ви можете визначати кастомні резолвери в шлюзі для обробки складних перетворень даних або для отримання даних з кількох сервісів та їх об'єднання в єдиний результат.
- Спільне використання контексту: Часто необхідно ділитися контекстною інформацією між шлюзом та віддаленими сервісами, наприклад, токенами автентифікації або ідентифікаторами користувачів. Цього можна досягти, передаючи контекстну інформацію як частину процесу делегування запиту.
- Обробка помилок: Реалізуйте надійну обробку помилок для коректного реагування на помилки, що виникають у віддалених сервісах. Це може включати логування помилок, повернення зрозумілих користувачеві повідомлень про помилки або повторні спроби невдалих запитів.
Вибір між зшиванням схем та Apollo Federation
Хоча зшивання схем є життєздатним варіантом для Федерації GraphQL, Apollo Federation стала популярнішим вибором завдяки своїм розширеним функціям та покращеному досвіду розробників. Ось порівняння двох підходів:
Функція | Зшивання схем | Apollo Federation |
---|---|---|
Визначення схеми | Використовує існуючу мову схем GraphQL | Використовує декларативну мову схем з директивами |
Планування запитів | Вимагає ручного делегування запитів | Автоматичне планування запитів шлюзом Apollo |
Розширення типів | Обмежена підтримка | Вбудована підтримка розширень типів |
Ключові директиви | Не підтримується | Використовує директиву @key для ідентифікації сутностей |
Розподілене трасування | Вимагає ручної реалізації | Вбудована підтримка розподіленого трасування |
Інструменти та екосистема | Менш зрілі інструменти | Більш зрілі інструменти та велика спільнота |
Складність | Може бути складним в управлінні у великих системах | Розроблено для великих і складних систем |
Коли обирати зшивання схем:
- У вас є існуючі сервіси GraphQL і ви хочете швидко їх об'єднати.
- Вам потрібне просте рішення для федерації і ви не потребуєте розширених функцій.
- У вас обмежені ресурси і ви хочете уникнути накладних витрат на налаштування Apollo Federation.
Коли обирати Apollo Federation:
- Ви будуєте велику і складну систему з кількома командами та сервісами.
- Вам потрібні розширені функції, такі як розширення типів, ключові директиви та розподілене трасування.
- Вам потрібне більш надійне та масштабоване рішення для федерації.
- Ви віддаєте перевагу більш декларативному та автоматизованому підходу до федерації.
Реальні приклади та випадки використання
Ось кілька реальних прикладів того, як можна використовувати Федерацію GraphQL, включаючи зшивання схем:
- E-commerce платформа: Платформа електронної комерції може використовувати Федерацію GraphQL для об'єднання даних з кількох сервісів, таких як сервіс каталогу продуктів, сервіс користувачів, сервіс замовлень та платіжний сервіс. Це дозволяє клієнтам легко отримувати всю необхідну інформацію для відображення деталей продукту, профілів користувачів, історії замовлень та платіжної інформації.
- Платформа соціальних мереж: Соціальна мережа може використовувати Федерацію GraphQL для об'єднання даних з сервісів, які керують профілями користувачів, постами, коментарями та лайками. Це дозволяє клієнтам ефективно отримувати всю інформацію, необхідну для відображення профілю користувача, його постів, а також коментарів та лайків, пов'язаних з цими постами.
- Додаток для фінансових послуг: Додаток для фінансових послуг може використовувати Федерацію GraphQL для об'єднання даних з сервісів, що керують рахунками, транзакціями та інвестиціями. Це дозволяє клієнтам легко отримувати всю необхідну інформацію для відображення балансів рахунків, історії транзакцій та інвестиційних портфелів.
- Система управління контентом (CMS): CMS може використовувати Федерацію GraphQL для інтеграції даних з різних джерел, таких як статті, зображення, відео та контент, створений користувачами. Це дозволяє створити єдиний API для отримання всього контенту, пов'язаного з певною темою або автором.
- Додаток для охорони здоров'я: Інтеграція даних пацієнтів з різних систем, таких як електронні медичні картки (EHR), результати лабораторних досліджень та планування прийомів. Це пропонує лікарям єдину точку доступу до всебічної інформації про пацієнта.
Найкращі практики для зшивання схем
Щоб забезпечити успішну реалізацію зшивання схем, дотримуйтесь цих найкращих практик:
- Ретельно плануйте свою схему: Перед тим, як почати зшивати схеми, ретельно сплануйте структуру уніфікованої схеми. Це включає визначення зв'язків між типами з різних схем, перейменування типів та полів для уникнення конфліктів та врахування загальних патернів доступу до даних.
- Використовуйте послідовні конвенції іменування: Прийміть послідовні конвенції іменування для типів, полів та операцій у всіх сервісах. Це допоможе уникнути конфліктів і полегшить розуміння уніфікованої схеми.
- Документуйте свою схему: Ретельно документуйте уніфіковану схему, включаючи описи типів, полів та операцій. Це полегшить розробникам розуміння та використання схеми.
- Моніторте продуктивність: Моніторте продуктивність шлюзу та віддалених сервісів для виявлення та усунення будь-яких вузьких місць у продуктивності. Використовуйте інструменти, такі як розподілене трасування, для відстеження запитів між кількома сервісами.
- Впроваджуйте безпеку: Впроваджуйте відповідні заходи безпеки для захисту шлюзу та віддалених сервісів від несанкціонованого доступу. Це може включати використання механізмів автентифікації та авторизації, а також валідацію вхідних даних та кодування вихідних.
- Версіонуйте свою схему: У міру розвитку ваших схем, версіонуйте їх належним чином, щоб клієнти могли продовжувати використовувати старіші версії схеми без збоїв. Це допоможе уникнути критичних змін та забезпечити зворотну сумісність.
- Автоматизуйте розгортання: Автоматизуйте розгортання шлюзу та віддалених сервісів, щоб зміни могли бути розгорнуті швидко та надійно. Це допоможе зменшити ризик помилок та покращити загальну гнучкість системи.
Висновок
Федерація GraphQL зі зшиванням схем пропонує потужний підхід до створення уніфікованих API з кількох сервісів у мікросервісній архітектурі. Розуміючи її основні концепції, переваги, обмеження та техніки реалізації, ви можете використовувати зшивання схем для спрощення доступу до даних, покращення масштабованості та підвищення зручності підтримки. Хоча Apollo Federation стала більш просунутим рішенням, зшивання схем залишається життєздатним варіантом для простіших сценаріїв або при інтеграції існуючих сервісів GraphQL. Ретельно зважте ваші конкретні потреби та вимоги, щоб вибрати найкращий підхід для вашої організації.